﻿#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

//auto 关键字
//在早期的C/C++中auto 的含义是：使用auto 修饰变量是具有自动存储的局部变量，后来这个不重要了，因为变量是存放在栈中的，栈中
//定义的变量均是自动便令，因为栈帧销毁的时候其中的变量也跟着销毁，故而早些年auto 失去了意义。而在c++11 中变废为宝，将此auto
//赋予了新的意义；利用auto 定义的变量不可以再指定类型；auto 不再是一个存储类型指示符，而是作为一个新的类型指示符来指示编译器，auto 声明
//的变量必须由编译器再编译时期推到而得到的
//用auto 声明指针的时候，用auto 与 auto* 没有任何区别，但用auto 声明引用类型时必须加&
//当在同一行声明多个变量的时候，这些变量必须是相同的类型否则编译器就会报错，因为编译器实际上只会堆其中的一个类型进行推到，然后用推导出
//的类型去定义其他变量
//auto 不能作为函数的参数，可以作为返回值，但是使用的时候必须要小心
//auto 不能直接用来声明数组
//int main()
//{
//	//auto aa = 1, bb = 1.0;//错误的写法
//	auto aa = 1, bb = 2;
//	//auto array[] = { 1, 2,3 };//auto 不可以用来推到数组的类型
//	//auto 作函数的返回值存在一个很大的弊端，可能导致使用的人一层一层去查
//	//在实际的应用当中，当一个变量的类型名称很长的时候就可以使用auto 来便利书写，例如：迭代器类型
//	return 0;
//}

//范围for 
//对于一个有范围的集合而言，由于程序员来说明的范围是多余的，有时候还会容易犯错所以c++11中引入了基于范围的for 循环
//for 循环后的括号由冒号":" 分为两部分，第一部分是范围内用于迭代的变量，第二部分则表示被迭代的范围，自动迭代，自动取数据，自动判断结束
//范围for 可以用作到数组和容器对象上进行遍历
//范围for 的底层很简单，容器遍历实际就是替换成迭代器，从汇编层面可以显然看出
//int main()
//{
//	int array[] = { 1,2,3,4,5,6,7 };
//	//普通的for 循环
//	for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
//	{
//		cout << array[i] << " ";
//	}
//	cout << endl;
//
//	//使用范围for
//	for (auto e : array)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//	//自动取数组array 中的数据赋值给e m自动++，依次取数组中的数据并自动判断结束
//	//意味着e 是数组中的数据䣌拷贝，想要改变数组中的数据就得使用引用传参
//	for (auto& e : array)
//	{
//		e *= 2;
//	}
//	for (auto e : array)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//	//改进，倘若数组中的数据很大，直接赋值给e 会调用拷贝构造函数，会消耗并付出代价；使用引用接收
//	//范围for 除了可以用来遍历数组中的数据还可以用来遍历容器；
//	return 0;
//}

//string 的本质是一个basic_string 的类的char 类型的模板；
//string 的构造函数，无参、string对象拷贝构造，string 对象一部分的拷贝构造，字符串，字符串的一部分，n个字符，迭代器区间
void test1()
{
	string s1;
	string s2("hello world");
	string s3(s2);
	string s4(s2, 6, 10);
	string s5(4, 'h');

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	cout << s5 << endl;
	//三种遍历访问的方式，方法一：下标+[] 方法二：迭代器，方法三：范围for ,本质上是两种访问方式，下标+[] 与迭代器访问
	for (auto& e : s2)
	{
		e += 1;
	}
	cout << s2 << endl;
	
	int i = 0;
	s2[i] += 1;
	cout << s2 << endl;

	//迭代器
	string::iterator it = s2.begin();
	while (it != s2.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	//字符串末尾的\0 并非是有效的字符，而是一个标识字符，可以将迭代器想象成向指针一样的东西
	//迭代器作为六大组件之一，是一个通用的访问方式
	//还有const 迭代器
	const string s6(s2);
	string::const_iterator it2 = s6.begin();
	//写成const_iterator 就代表着const 修饰了迭代器
	//这里使用auto 就非常方便
	//auto it2 = s6.begin();
	while (it2 != s6.end())
	{
		cout << *it2 << " ";
		++it2;
	}
	cout << endl;
}

//string 底层的析构函数不用管，因为string 底层可能是动态开辟的空间会自动释放自动调用
//operator= 赋值运算符重载，string 对象，字符串，单个字符
//迭代器 Iterators,迭代器是一个左闭右开的区间

int main()
{
	test1();
	return 0;
}